package com.ztr.conversion.pdf2Img;

import com.google.common.collect.Lists;
import com.ztr.conversion.util.MyFileUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * Pdf 转 PNG 工具类
 * </p>
 */
@Slf4j
public class Pdf2PngUtil {

    /**
     * dpi越大转换后越清晰，相对转换速度越慢
     */
    private static final Integer DPI = 100;

    /**
     * 转换后的图片类型
     */
    private static final String IMG_TYPE = "png";


    /**
     * 将PDF文档转换为PNG图像数组。
     * <p>
     * 此方法接受一个PDF文档的字节数组作为输入，使用PDFBox库将每个页面渲染为PNG图像，
     * 然后将这些图像作为字节数组的列表返回。这种方法适用于需要将PDF文档的每一页
     * 作为单独的图像处理的场景，比如文档预览或图像处理。
     *
     * @param pdfBytes PDF文档的字节数组表示。
     * @return 包含每页PDF转换为PNG图像的字节数组的列表。
     * @throws Exception 如果在加载PDF文档或渲染图像过程中发生错误。
     */
    @SneakyThrows(Exception.class)
    public List<byte[]> pdf2Png(byte[] pdfBytes) {
        // 初始化存储PNG图像字节数组的列表
        List<byte[]> result = new ArrayList<>();
        try (PDDocument document = PDDocument.load(pdfBytes)) {
            // 创建PDF渲染器
            PDFRenderer renderer = new PDFRenderer(document);
            // 遍历文档的每一页
            for (int i = 0; i < document.getNumberOfPages(); ++i) {
                // 渲染当前页面为指定DPI的BufferedImage
                BufferedImage bufferedImage = renderer.renderImageWithDPI(i, DPI);
                // 创建 ByteArrayOutputStream 以存储图像的字节流
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                // 将BufferedImage写入 ByteArrayOutputStream 为PNG格式
                ImageIO.write(bufferedImage, IMG_TYPE, out);
                // 将图像的字节流添加到结果列表
                result.add(out.toByteArray());
            }
        }
        // 返回包含所有页面PNG图像的字节数组列表
        return result;
    }


    /**
     * 将PDF文档转换为PNG图像文件列表。
     *
     * @param pdfBytes    PDF文档的字节流形式。
     * @param imgRootPath 图像文件保存的根目录路径。
     * @return 包含转换后的PNG图像文件的文件列表。
     */
    public List<File> pdf2Png(byte[] pdfBytes, String imgRootPath) {
        // 调用pdf2Png方法将PDF转换为PNG图像的字节流列表
        List<byte[]> pngBytesList = this.pdf2Png(pdfBytes);
        // 初始化一个空的文件列表，用于存储转换后的PNG图像文件
        List<File> pngFileList = Lists.newArrayList();
        // 遍历PNG图像的字节流列表
        for (int i = 0; i < pngBytesList.size(); i++) {
            // 构建每个PNG图像文件的路径
            String imgPath = imgRootPath + "/" + (i + 1) + ".png";
            // 将PNG图像的字节流写入文件，并添加到文件列表中
            File pngFile = MyFileUtil.writeFileContent(pngBytesList.get(i), imgPath);
            pngFileList.add(pngFile);
        }
        // 返回包含转换后的PNG图像文件的文件列表
        return pngFileList;
    }


}
